<template>
  <div class="duck-man duck-content">
    <div class="column-layout_wrap">
      <ul class="column-layout">
        <template v-for="item in 3000">
          <li :key="item" v-if="defer(item)">
            {{ item }}
          </li>
        </template>
      </ul>
    </div>
  </div>
  <!-- <d-loading /> -->
  <div class="duck-man duck-content rotate-menu">
    <a-button @click="sendRequest">发起请求</a-button>
    <div class="menu" v-loading="loading" loading-tip="hahaha..." loading-size="default"></div>
  </div>
  <ul></ul>
</template>

<script setup lang="ts">
  import { ref, onMounted } from 'vue'
  import { endLoop } from '@/shared'
  import { useDefer } from '@/utils'

  const { defer } = useDefer(3000)

  const loading = ref<boolean>(false)

  const sendRequest = () => {
    loading.value = true
    setTimeout(() => {
      loading.value = false
    }, 1900)
  }
  /**
   * 策略模式 ---------- begin
   */
  const jobList = ['FE', 'BE']
  const strategies = {
    checkRole: (value: string): boolean => {
      return value === 'juejin'
    },
    checkGrade: (value: number): boolean => {
      return value === 1
    },
    checkJob: (value: string): boolean => {
      return jobList.indexOf(value) > -1
    },
    checkEatType: (value: string): boolean => {
      return value === 'eat melons'
    }
  }

  // const Validator = function() {}

  class Validator {
    cache: any[]
    constructor(cache: []) {
      this.cache = cache
    }
    add(value: string | number, method: string) {
      this.cache.push(function () {
        return strategies[method](value)
      })
    }
    check() {
      return this.cache.map((item: Function) => {
        const data = item()
        if (!data) {
          return false
        }
        return true
      })
    }
  }
  const compose = () => {
    const validator = new Validator([])
    const data = {
      role: 'juejin',
      grade: 3
    }
    validator.add(data.role, 'checkRole')
    validator.add(data.grade, 'checkGrade')
    const result = validator.check()
    return result
  }
  compose()
  /**
   * 策略模式 ---------- end
   */

  /**
   * 多张发票找总数为目标总数 ---------- begin
   */
  function findClosestNumbers(numArr: number[], targetSum: number, numCount: number) {
    let closestSum = 0
    let closestNums: number[] = []

    function backtrack(tempSum: number, tempNums: number[], startIndex: number) {
      if (tempNums.length === numCount) {
        if (tempSum <= targetSum && Math.abs(tempSum - targetSum) < Math.abs(closestSum - targetSum)) {
          closestSum = tempSum
          closestNums = tempNums.slice()
        }
        return
      }

      for (let i = startIndex; i < numArr.length; i++) {
        tempNums.push(numArr[i])
        backtrack(tempSum + numArr[i], tempNums, i + 1)
        tempNums.pop()
      }
    }

    backtrack(0, [], 0)

    return closestNums
  }
  // 测试代码
  const numArr = [20.09, 401, 658, 654.48, 141.27]
  const total = 280
  const count = 2
  const resNum = findClosestNumbers(numArr, total, count)

  Array.prototype.sum = function () {
    let sum = 0
    for (let i = 0; i < this.length; i++) {
      sum += this[i]
    }
    return sum
  }
  /**
   * 多张发票找总数为目标总数 ---------- end
   */

  /**
   * endLoop test ----------begin
   */
  let testArr = [
    { value: 1, label: 1 },
    { value: 2, label: 2 },
    { value: 3, label: 3 },
    { value: 4, label: 4 },
    { value: 5, label: 5 }
  ]
  const options = [
    { name: 1, option: [{ key: 'a', value: 'A' }] },
    { name: 6, option: [{ key: 'b', value: 'B' }] },
    { name: 7, option: [{ key: 'c', value: 'C' }] },
    { name: 8, option: [{ key: 'd', value: 'D' }] },
    { name: 9, option: [{ key: 'e', value: 'E' }] }
  ]
  console.time('test1')
  testArr.forEach((item: Record<string, any>) => {
    if (item.value === 3) {
      item.option = [{ key: 'b', value: 'B' }]
    }
  })
  console.timeEnd('test1')

  console.time('test2')
  endLoop(testArr, (item: Record<string, any>) => {
    if (item.value === 3) {
      item.option = [{ key: 'b', value: 'B' }]
      return true
    }
  })

  console.timeEnd('test2')

  /**
   * endLoop test ----------end
   */

  /* test javascript origin vDom */
  onMounted(() => {
    // const ulDom: HTMLUListElement = document.querySelector('ul')!
    const fruits: number[] = new Array(10000).fill(10)
    const fragment = new DocumentFragment()
    fruits.forEach((fruit) => {
      const liDom: HTMLElement = document.createElement('li')!
      liDom.textContent = fruit as never as string
      // ulDom?.appendChild(liDom)
      fragment.appendChild(liDom)
    })
    // ulDom?.appendChild(fragment)
  })
  /* test javascript origin vDom */
</script>

<style lang="less" scoped>
  /* 旋转菜单 */
  .menuItem {
    width: 60px;
    height: 60px;
    border-radius: 50%;
  }
  .rotate-menu {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 50vh;
    background: linear-gradient(45deg, deeppink, skyblue);

    .menu {
      position: relative;
      width: 30%;
      min-height: 110px;
      display: flex;
      justify-content: center;
      align-items: center;
      // &:hover .menu-item {
      //   transform: rotate(calc(360deg / 5 * var(--i)));
      // }

      .btn {
        .menuItem();
        position: absolute;
        z-index: 99;
        width: 100px;
        height: 100px;
        background-color: #fff;
        box-shadow: 0 3px 4px rgba(0, 0, 0, 0.15);
        &:hover .menu-item {
          transform: rotate(calc(360deg / 5 * var(--i)));
        }
      }

      .menu-item {
        .menuItem();
        display: inline-block;
        background-color: pink;
        width: 80px;
        height: 80px;
        z-index: 1;
        box-shadow: 0 3px 4px rgba(0, 0, 0, 0.15);
        position: absolute;
        left: 0;

        // key words
        transform: rotate(0deg) translate(10px, 10px);

        transform-origin: center -80px;
        transition-delay: calc(0.1s * var(--i));
        transition: 0.5s;
      }
    }
  }
  /* 旋转菜单 */

  /* column 布局 */
  .column-layout_wrap {
    display: flex;
    overflow-y: auto;
    width: 1000px;

    scroll-snap-type: x mandatory;

    .column-layout {
      list-style: none;
      margin: 0;
      padding: 0;
      border: 0;
      font-size: 100%;
      font: inherit;
      vertical-align: baseline;

      height: 200px;
      // column-width: 120px;
      columns: 3;

      li {
        display: inline-flex;
        width: 80px;
        height: 80px;
        margin: 10px;
        color: #333;
        font-size: 22px;
        background-color: cadetblue;
      }
      li:nth-child(6n + 1) {
        scroll-snap-align: start;
        background-color: rgb(106, 132, 133);
      }
    }
  }
  /* column 布局 */
</style>
